home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / µSim 1.0.5 / FabLibsƒ / FabWmemman.c < prev    next >
Encoding:
Text File  |  1995-11-17  |  5.7 KB  |  258 lines  |  [TEXT/CWIE]

  1. /*
  2. ANSI C _working_ equivalents for malloc, free, realloc, calloc;
  3. as a free bonus, you get ffcalloc() and fgetallocsize()
  4. unexplicably missing from the standard libraries.
  5.  
  6. malloc & free implementation based on Kernighan&Ritchie, 2nd ed.;
  7. realloc, calloc, ffcalloc, fgetallocsize by Fabrizio Oddone.
  8.  
  9. 2/1/95
  10. Modified the realloc routine in order to behave as described in
  11. section 7.10.3.4 of ANSI/ISO-C;
  12. that is:
  13. if ptr is a null pointer, realloc() allocates size bytes,
  14. else if size is 0, the memory block pointed to by ptr is freed.
  15. */
  16.  
  17.  
  18. //#include    <StdLib.h>
  19. #include    <String.h>
  20. #include    "UtilsSys7.h"
  21. #include    "FabWmemman.h"
  22.  
  23. //typedef long Align;
  24.  
  25. typedef union header Header;
  26.  
  27. union header {
  28.     struct {
  29.         Header *ptr;    // next block if on free list
  30.         size_t    size;        // size of this block (not bytes but MEMORY_UNITs)
  31.         } s;
  32. //    Align    x, y;
  33.     };
  34.  
  35. //#define    USETEMPORARYMEMORY    1
  36. //#define    USE64BITUNITS    1
  37.  
  38. #ifdef    USE64BITUNITS
  39. #define    MEMORY_UNIT    sizeof(Header)
  40. #else
  41. #define    MEMORY_UNIT    4    //sizeof(Header)
  42. #endif
  43.  
  44. /* NALLOC determines the amount of memory asked to the Mac OS */
  45. /* the allocated block is then handled by malloc */
  46. /* currently morecore asks "at least 64Kbytes" (you may want smaller blocks) */
  47.  
  48. #define    NALLOC    (2048UL / MEMORY_UNIT)    // minimum # units to request
  49.  
  50.  
  51. static Header base;    // empty list to get started
  52. static Header *freep = NULL;    // start of free list
  53.  
  54. static Header *morecore(size_t nu);
  55.  
  56. #define    HDR(p)    ((Header *)p)
  57.  
  58. void *fmalloc(size_t nbytes)
  59. {
  60. Ptr    p;
  61. Header *prevp;
  62. size_t    nunits, tempsize;
  63.  
  64. //DebugStr("\pNow entering fmalloc");
  65. nunits = (nbytes + sizeof(Header) - 1) / MEMORY_UNIT + 1;
  66. if ((prevp = freep) == NULL) {    // no free list yet
  67.     base.s.ptr = freep = prevp = &base;
  68.     base.s.size = 0;
  69.     }
  70.  
  71. for (p = (Ptr)prevp->s.ptr; ; prevp = HDR(p), p = (Ptr)HDR(p)->s.ptr) {
  72.     tempsize = HDR(p)->s.size;
  73.     if (tempsize >= nunits) {    // big enough
  74.         if (
  75. #ifdef    USE64BITUNITS
  76.         tempsize == nunits
  77. #else
  78.         tempsize <= nunits + 1
  79. #endif
  80.         )    // exactly
  81.             prevp->s.ptr = HDR(p)->s.ptr;
  82.         else {    // allocate tail end
  83.             HDR(p)->s.size -= nunits;
  84.             //p = (Header *)((Ptr)p + p->s.size * MEMORY_UNIT);
  85.             p += HDR(p)->s.size * MEMORY_UNIT;
  86.             HDR(p)->s.size = nunits;
  87.             }
  88.         freep = prevp;
  89.         return (p + sizeof(Header));
  90.         }
  91.     if (HDR(p) == freep)    // wrapped around free list
  92.         if ((p = (Ptr)morecore(nunits)) == NULL)
  93.             return NULL;    // none left
  94.     }
  95. }
  96.  
  97.  
  98. static Header *morecore(size_t nu)
  99. {
  100. Header *up;
  101.  
  102. if (nu < NALLOC)
  103.     nu = NALLOC;
  104. if (NULL == (up = (Header *)
  105. #ifdef USETEMPORARYMEMORY
  106.     NewHandleGeneral
  107. #else
  108.     NewPtr
  109. #endif
  110.         (nu * MEMORY_UNIT)))
  111.     return NULL;    // no space left
  112.  
  113. #ifdef USETEMPORARYMEMORY
  114. HLock((Handle)up);
  115. up = (Header *)*(Handle)up;
  116. #endif
  117. up->s.size = nu;
  118. ffree(up + 1);
  119. return freep;
  120. }
  121.  
  122. void ffree(void *bp)
  123. {
  124. Header *p, *tmp;
  125.  
  126. bp = HDR(bp) - 1;    // point to block header
  127. // !(bp > p && bp < p->s.ptr)
  128. //for (p = freep; bp <= p || bp >= p->s.ptr; p = p->s.ptr)
  129. //    if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
  130. //        break;    // freed block at start or end of arena
  131.  
  132. p = freep;
  133. tmp = p->s.ptr;
  134. while (bp <= p || bp >= tmp) {
  135.     if (p >= tmp && (bp > p || bp < tmp))
  136.         break;    // freed block at start or end of arena
  137.     p = p->s.ptr;
  138.     tmp = p->s.ptr;
  139.     }
  140.  
  141. if ((Ptr)bp + HDR(bp)->s.size * MEMORY_UNIT == (Ptr)tmp) {    // join to upper neighbor
  142.     HDR(bp)->s.size += tmp->s.size;
  143.     HDR(bp)->s.ptr = tmp->s.ptr;
  144.     }
  145. else
  146.     HDR(bp)->s.ptr = tmp;
  147. if ((Ptr)p + p->s.size * MEMORY_UNIT == (Ptr)bp) {    // join to lower neighbor
  148.     p->s.size += HDR(bp)->s.size;
  149.     p->s.ptr = HDR(bp)->s.ptr;
  150.     }
  151. else
  152.     p->s.ptr = bp;
  153. freep = p;
  154. }
  155.  
  156. /* reallocates and copies the old block only when necessary */
  157.  
  158. void *frealloc(void *ap, size_t s)
  159. {
  160. Ptr    bp;
  161. Header *p, *new_block;
  162. void *r = ap;
  163. size_t    cursize, nunits, temp;
  164.  
  165. if (ap) {
  166.     if (s) {
  167.         bp = (Ptr)ap - sizeof(Header);
  168.         nunits = (s + sizeof(Header) - 1) / MEMORY_UNIT + 1;
  169.         cursize = HDR(bp)->s.size;
  170.         if (nunits
  171.         #ifndef    USE64BITUNITS
  172.             + 1
  173.         #endif
  174.             < cursize) {
  175.         
  176.             HDR(bp)->s.size = nunits;
  177.             bp += nunits * MEMORY_UNIT;
  178.             HDR(bp)->s.size = cursize - nunits;
  179.             ffree(bp + sizeof(Header));
  180.             }
  181.         else if (nunits > cursize) {
  182.             for (p = freep; !(bp > (Ptr)p && bp < (Ptr)p->s.ptr); p = p->s.ptr)
  183.                 if (p >= p->s.ptr && (bp > (Ptr)p || bp < (Ptr)p->s.ptr))
  184.                     break;    // freed block at start or end of arena
  185.             temp = p->s.ptr->s.size + cursize;
  186.             if ((bp + cursize * MEMORY_UNIT == (Ptr)p->s.ptr) && (temp >= nunits)) {
  187.         // we can expand the block upwards in memory
  188.                 if (
  189.         #ifdef    USE64BITUNITS
  190.                 temp == nunits
  191.         #else
  192.                 temp <= nunits + 1
  193.         #endif
  194.                 ) {
  195.         // there is an adjacent free block matching exactly our needs
  196.                     HDR(bp)->s.size = temp;
  197.                     p->s.ptr = p->s.ptr->s.ptr;
  198.                     }
  199.                 else {
  200.         // we need to split the adjacent block
  201.                     new_block = (Header *) (bp + nunits * MEMORY_UNIT);
  202.                     new_block->s.ptr = p->s.ptr->s.ptr;
  203.                     new_block->s.size = temp - nunits;
  204.                     HDR(bp)->s.size = nunits;
  205.                     p->s.ptr = new_block;
  206.                     }
  207.                 freep = p;
  208.                 }
  209.             else {
  210.         // expanding not possible; reallocate, copy and free the old block
  211.                 if (r = fmalloc(s)) {
  212.                     BlockMoveData(ap, r, cursize * MEMORY_UNIT - sizeof(Header));
  213.                     ffree(ap);
  214.                     }
  215.                 }
  216.             }
  217.         }
  218.     else {
  219.         ffree(ap);
  220.         r = NULL;
  221.         }
  222.     }
  223. else
  224.     r = fmalloc(s);
  225.  
  226. return r;
  227. }
  228.  
  229. size_t fgetallocsize(const void *ap)
  230. {
  231. return ((Header *)ap - 1)->s.size * MEMORY_UNIT - sizeof(Header);
  232. }
  233.  
  234. void *fcalloc(size_t nelem, size_t nsize)
  235. {
  236. void *p;
  237. size_t    nbytes = nelem * nsize;
  238.  
  239. if (p = fmalloc(nbytes)) {
  240. // memset is poorly implemented, so we use a better one
  241.     MyZeroBuffer(p, numOfLongs(nbytes + 3));
  242.     //(void) memset(p, 0, nbytes);
  243.     }
  244. return p;
  245. }
  246.  
  247. void *ffcalloc(size_t s)
  248. {
  249. void *p;
  250.  
  251. if (p = fmalloc(s)) {
  252. // memset is poorly implemented, so we use a better one
  253.     MyZeroBuffer(p, numOfLongs(s + 3));
  254.     //(void) memset(p, 0, nbytes);
  255.     }
  256. return p;
  257. }
  258.